﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;


namespace ProUpdater
{
    public partial class Form1 : Form
    {
        private static string serverXml;
        private static string deskXml;
        private Dictionary<string, FileInfo> deskFiles;
        private Dictionary<string, FileInfo> serverFiles;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            TextBoxAddText(ServerXmlInnerText("xml/info"));
            labelfiles.Text = "共计文件:" + ServerFiles.Count;
            UpdatarServerFiles();
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            e.Graphics.DrawImage(Properties.Resources.升级x300, new Rectangle(2, -18, 95, 246));
        }

        //任意位置可拖动
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case 0x0201: //鼠标左键按下的消息
                    m.Msg = 0x00A1; //更改消息为非客户区按下鼠标
                    m.LParam = IntPtr.Zero; //默认值
                    m.WParam = new IntPtr(2);//鼠标放在标题栏内
                    base.WndProc(ref m);
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
        public void UpdatarServerFiles()
        {
            Task.Run(() =>
            {
                bool result = true;
                foreach (var v in ServerFiles)
                {
                    TextBoxAddText($"下载文件：{v.Value.Name}");
                    TextBoxAddText($"{v.Value.Info}");
                    //检查是否存在
                    if (DeskFiles.ContainsKey(v.Key) && new Version(v.Value.Version) <= new Version(DeskFiles[v.Key].Version))
                    {
                        TextBoxAddText($"下载文件：{v.Value.Name} 文件不需要更新");
                        continue;
                    }

                    var s = DownloadFile(v.Value.Name, v.Value.Path);
                    try
                    {
                        s.Wait();
                    }
                    catch (Exception ex)
                    {
                        TextBoxAddText(ex.Message);
                        TextBoxAddText($"下载文件：{v.Value.Name} 失败");
                        result = false;
                        continue;
                    }
                    TextBoxAddText($"下载文件：{v.Value.Name} 成功");
                }
                this.Invoke(new Action(() =>
                {
                    //保存服务xml文件到本地
                    if (result)
                    {
                        XmlDocument xml = new XmlDocument();//声明xml    
                        xml.LoadXml(ServerXml);
                        xml.Save("wenupdater.xml");
                        MessageBox.Show("升级完成！");
                        foreach (var v in ServerFiles)
                        {
                            if (v.Value.Run)
                            {
                                string deskPath = Application.StartupPath + "\\" + v.Value.Name;
                                try
                                {                
                                    Process pr = new Process();//声明一个进程类对象
                                    pr.StartInfo.FileName = deskPath;
                                    pr.Start();
                                }
                                catch { MessageBox.Show(deskPath, "运行失败！"); }
                            }
                        }
                    }
                    else
                    {
                        MessageBox.Show("升级失败！");
                    }

                    string vBatFile = Path.GetDirectoryName(Application.ExecutablePath) + "\\Zswang.bat";
                    using (StreamWriter vStreamWriter = new StreamWriter(vBatFile, false, Encoding.Default))
                    {
                        vStreamWriter.Write(string.Format(
                           ":del\r\n" +
                            " del \"{0}\"\r\n" +
                            "if exist \"{0}\" goto del\r\n" + //此处已修改
                            "del %0\r\n", Application.ExecutablePath));
                    }
                    WinExec(vBatFile, 0);
                    Application.Exit();
                }));
            });
        }

        [DllImport("kernel32.dll")]
        public static extern uint WinExec(string lpCmdLine, uint uCmdShow);

        #region 输出日志
        public void TextBoxAddText(string text)
        {
            TextBoxAddText(text, "");
        }
        public void TextBoxAddText(string text, params string[] strs)
        {
            textBox1.Invoke(new Action(() =>
            {
                textBox1.Text += string.Format(text + "\r\n", strs);
                this.textBox1.Focus();//获取焦点
                this.textBox1.Select(this.textBox1.TextLength, 0);//光标定位到文本最后
                this.textBox1.ScrollToCaret();//滚动到光标处

            }));
        }

        #endregion

        //从服务器下载文件

        public Task DownloadFile(string fileName, string url)
        {
            string deskPath = Application.StartupPath + "\\" + fileName;

            if (!Directory.Exists(Path.GetDirectoryName(deskPath)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(deskPath));
            }
            WebClient wc = new WebClient();
            wc.DownloadProgressChanged += (s, e) =>
            {
                this.Invoke(new Action(() =>
                {
                    this.progressBar1.Minimum = 0;
                    this.progressBar1.Maximum = (int)e.TotalBytesToReceive;
                    this.progressBar1.Value = (int)e.BytesReceived;

                    label2.Text = string.Format("已下载：{0}KB/{1}KB", (int)e.BytesReceived / 1024, (int)e.TotalBytesToReceive / 1024);
                }));
            };

            return wc.DownloadFileTaskAsync(url, deskPath);
        }


        //下载服务器最新的文件
        public void DownloadFile(string url)
        {
            string path = Application.StartupPath + "\\UpdatarFile";
            //判定文件夹是否存在
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            WebClient wc = new WebClient();
            wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            string fileUrl = url;

            //获取本地文件路劲
            string saveFileName = fileUrl.Substring(fileUrl.LastIndexOf('/') + 1);
            string saveFilePath = string.Format(@"{0}\{1}", path, saveFileName);

            wc.DownloadFileCompleted += (s, e) =>
            {
                if (e.Error == null)
                {
                    ////下载成功后执行内容
                    //Process pr = new Process();//声明一个进程类对象
                    //pr.StartInfo.FileName = saveFilePath;
                    //pr.Start();
                }
            };
            wc.DownloadProgressChanged += (s, e) =>
            {
                this.progressBar1.Minimum = 0;
                this.progressBar1.Maximum = (int)e.TotalBytesToReceive;
                this.progressBar1.Value = (int)e.BytesReceived;

                label2.Text = string.Format("已下载：{0}KB/{1}KB", (int)e.BytesReceived / 1024, (int)e.TotalBytesToReceive / 1024);
            };

            wc.DownloadFileAsync(new Uri(fileUrl), saveFilePath);
        }


        //本地xml文件
        public static string DeskXml
        {
            get
            {
                if (deskXml == null)
                {
                    XmlDocument xml = new XmlDocument();//声明xml    
                    xml.Load("wenupdater.xml");//按路径读xml文件 
                    deskXml = xml.InnerXml;
                }
                return deskXml;
            }
        }
        //获取本地列表
        public Dictionary<string, FileInfo> DeskFiles
        {
            get
            {
                if (deskFiles == null)
                {
                    deskFiles = new Dictionary<string, FileInfo>();
                    XmlDocument xml = new XmlDocument();//声明xml    
                    xml.LoadXml(DeskXml);
                    var xs = xml.SelectNodes("xml/files/file");
                    foreach (XmlNode xn in xs)
                    {
                        FileInfo fileInfo = new FileInfo()
                        {
                            Name = xn.SelectSingleNode("name").InnerText,
                            Path = xn.SelectSingleNode("path").InnerText,
                            Version = xn.SelectSingleNode("version").InnerText,
                            Info = xn.SelectSingleNode("info").InnerText,
                            Run = bool.Parse(xn.SelectSingleNode("run").InnerText)
                        };
                        deskFiles.Add(xn.SelectSingleNode("name").InnerText, fileInfo);
                    }
                }
                return deskFiles;
            }
        }

        public Dictionary<string, FileInfo> ServerFiles
        {
            get
            {
                if (serverFiles == null)
                {
                    serverFiles = new Dictionary<string, FileInfo>();
                    XmlDocument xml = new XmlDocument();//声明xml    
                    xml.LoadXml(ServerXml);
                    var xs = xml.SelectNodes("xml/files/file");
                    foreach (XmlNode xn in xs)
                    {
                        FileInfo fileInfo = new FileInfo()
                        {
                            Name = xn.SelectSingleNode("name").InnerText,
                            Path = xn.SelectSingleNode("path").InnerText,
                            Version = xn.SelectSingleNode("version").InnerText,
                            Info = xn.SelectSingleNode("info").InnerText,
                            Run = bool.Parse(xn.SelectSingleNode("run").InnerText)
                        };
                        serverFiles.Add(xn.SelectSingleNode("name").InnerText, fileInfo);
                    }
                }
                return serverFiles;
            }
        }
        
        public class FileInfo
        {
            public string Name { get; set; }
            public string Path { get; set; }
            public string Version { get; set; }
            public string Info { get; set; }
            public bool Run { get; set; }
        }

        public static string ServerXml
        {
            get
            {
                if (serverXml == null)
                {
                    string serverxmlPath = XmlInnerText("xml/url");
                    XmlDocument xml = new XmlDocument();//声明xml    
                    xml.Load(serverxmlPath);//按路径读xml文件 
                    serverXml = xml.InnerXml;
                }
                return serverXml;
            }
        }

        //服务节点获取
        public static string ServerXmlInnerText(string nodeName)
        {
            try
            {
                XmlDocument xml = new XmlDocument();//声明xml    
                xml.LoadXml(ServerXml);
                XmlNode xn = xml.SelectSingleNode(nodeName);//指定节点
                return xn.InnerText;//返回节点信息
            }
            catch
            {
                return null;//如果错误返回空
            }
        }

        //版本比较
        public static bool VersionIF()
        {
            try
            {
                Version v1 = new Version(XmlInnerText("xml/version"));
                Version v2 = new Version(ServerXmlInnerText("xml/version"));

                if (v2 > v1)
                    return true;
                else
                    return false;
            }
            catch
            {
                return false;
            }
        }

        // 获取节点值
        public static string XmlInnerText(string nodeName)
        {
            try
            {
                XmlDocument xml = new XmlDocument();//声明xml    
                xml.LoadXml(DeskXml);
                XmlNode xn = xml.SelectSingleNode(nodeName);//指定节点
                return xn.InnerText;//返回节点信息
            }
            catch
            {
                return null;//如果错误返回空
            }
        }
    }
}